package com.duqc.sentinel.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.duqc.sentinel.domain.User;
import com.duqc.sentinel.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author duqc
 * @Date 2021/5/17
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    /**
     * 资源名称
     */
    public static final String RESOURCE_NAME_QUERY_USER_BY_NAME = "queryUserByUserName";
    public static final String ADD = "add";

    @Override
    public List<User> getList() {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "周慧敏", "18"));
        userList.add(new User(2, "关之琳", "20"));
        userList.add(new User(3, "王祖贤", "21"));
        return userList;
    }

    /**
     * value是资源名称，是必填项。blockHandler填限流处理的方法名称
     *
     * @param name
     * @return
     */
    @Override
    @SentinelResource(value = RESOURCE_NAME_QUERY_USER_BY_NAME,
            blockHandler = "queryUserByUserNameBlock",
            fallback = "queryUserByUserNameFallBack")
    public User queryByUserName(String name) {
        if (name == null || "".equals(name)) {
            //抛出异常
            throw new RuntimeException("queryByUserName() command failed, userName is null");
        }
        return new User(1, name, "20");
    }

    @Override
    @SentinelResource(value = ADD,
            blockHandler = "queryUserByUserNameBlock",
            fallback = "queryUserByUserNameFallBack")
    public String add(User user) {
        return null;
    }

    /**
     * 注意细节，一定要跟原函数的返回值和形参一致，并且形参最后要加个BlockException参数
     * 否则会报错，FlowException: null
     * 当抛出非BlockException的异常时，就会进入到fallback方法中，实现熔断机制
     *
     * @param name
     * @param e
     * @return
     */
    public User queryUserByUserNameBlock(String name, BlockException e) {
        e.printStackTrace();
        return new User(0, "用户名称：{" + name + "},资源访问被限流", "0");
    }

    public User queryUserByUserNameFallBack(String name, Throwable e) {
        //打印日志
        e.printStackTrace();
        return new User(0, "用户名称：{" + name + "},系统异常，请稍后重试", "0");
    }

}
